package com.stars.sun.reflect;

import com.stars.sun.annotation.MyPath;
import com.stars.sun.mvc.ActionInfo;
import com.stars.sun.mvc.MappingNode;
import com.stars.sun.service.BaseService;

import java.io.File;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by 340082 on 2018/2/7.
 *@author jiyx
 * 反射初始化参数，类扫描等等
 *
 */
public class MyReflect {

    private static String SERVICE_SCAN = "com";
    //这里是一个常量

    private ClassLoader classLoader = getClass().getClassLoader();
    //我们加载策略时的类加载器，我们任何类运行时信息必须来自该类加载器

    public static List<Class<? extends BaseService>> SERVICE_SCAN_LIST;
    //类列表

    public static MappingNode<ActionInfo> rootMapping ;

    /**
     * 所有扫描到的service基类
     */
    private List<File> classFiles = new ArrayList<File>();

    public void getPathClassForPath(String path ){
        SERVICE_SCAN = path;
        this.init();
    }



    /**
     * 初始化路径
     */
    private void init(){
        SERVICE_SCAN_LIST = new ArrayList<Class<? extends BaseService>>();
        File[] resources = getResources();
        //获取到包下所有的class文件
        Class<BaseService> baseService = null;
        try {
            baseService = (Class<BaseService>) classLoader.loadClass(BaseService.class.getName());
            //使用相同的加载器加载接口
        } catch (ClassNotFoundException e1) {
            throw new RuntimeException("未找到接口");
        }
        for (int i = 0; i < resources.length; i++) {
            try {
                //载入包下的类
                Class<?> clazz = classLoader.loadClass(filePathToClassPath(resources[i].getPath()));
                //判断是否是SERVICE的实现类并且不是SERVICE它本身，满足的话加入到策略列表
                if (BaseService.class.isAssignableFrom(clazz) && clazz != baseService) {
                    SERVICE_SCAN_LIST.add((Class<? extends BaseService>) clazz);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
        initUrlMapping();
    }

    private void initUrlMapping(){
        rootMapping = new MappingNode<ActionInfo>();
        for(Class<? extends BaseService> calzz : SERVICE_SCAN_LIST){
            Method[] methods = calzz.getMethods();
            String calssPath = getMyPathValueForBaseService(calzz);
            for(Method method : methods){
                String methodPath = getMyPathValueForMethod(method);
                if(methodPath==null){
                    continue;
                }
                ActionInfo actionInfo = new ActionInfo();
                actionInfo.setModuleType(calzz);
                actionInfo.setModuleMethod(method);
                rootMapping.add(calssPath + methodPath ,actionInfo);
            }
        }
        System.out.println(rootMapping);
    }

    private String getMyPathValueForBaseService(Class<? extends BaseService> calzz) {
        MyPath annotation = calzz.getAnnotation(MyPath.class);
        if(annotation != null){
            return annotation.value();
        }
        return "";
    }

    private String getMyPathValueForMethod(Method calzz) {
        MyPath annotation = calzz.getAnnotation(MyPath.class);
        if(annotation != null){
            return annotation.value();
        }
        return null;
    }



    //获取扫描的包下面所有的class文件
    private File[] getResources(){
        try {
            URI uri = classLoader.getResource(SERVICE_SCAN.replace(".", "/")).toURI();
            getFiles(uri.getPath());
            return classFiles.toArray(new File[0]);
        } catch (URISyntaxException e) {
            throw new RuntimeException("未找到资源");
        }
    }

    //处理路径取出文件夹下的.class
    private void getFiles(String path) {
        File file = new File(path);
        //将所有的文件进行遍历,取出其中的文件夹再次遍历
        File[] files = file.listFiles();
        for (int i = 0 ; i < files.length ; i++ ){
            File indexFile = files[i];
            if(indexFile.getName().endsWith(".class")){
                classFiles.add(indexFile);
            }else if(indexFile.isDirectory()){
                getFiles(indexFile.getPath());
            }
        }
    }


    public String filePathToClassPath(String filePath){
        if(!filePath.contains("classes")){
            throw new NullPointerException();
        }
        int classes = filePath.indexOf("classes");
        String s = filePath.substring(classes + 8).replace(".class", "").replaceAll("\\\\", ".");
//        //调试使用
//        System.out.println(s);
        return s;
    }

//    public static List<File> getClassFiles() {
//        return classFiles;
//    }
//
//    public static void setClassFiles(List<File> classFiles) {
//        MyReflect.classFiles = classFiles;
//    }
}
